package com.hhwy.components;

import com.hhwy.domain.DeformationCheck;
import com.hhwy.service.IDeformationCheckService;
import com.hhwy.utils.SpringBeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @desc 电缆变形检测
 * @since 2024/6/4
 */
@Component
public class DeformationCheckSocket {

    @Value("${deformation-socket.ip}")
    private String ip;

    @Value("${deformation-socket.port}")
    private Integer port;

    @Value("${deformation-socket.startFlag}")
    private String startFlag;

    @Value("${deformation-socket.endFlag}")
    private String endFlag;

    @Value("${deformation-socket.enable}")
    private boolean enable;

    private static final Logger log = LoggerFactory.getLogger(DeformationCheckSocket.class);

    private static final ThreadPoolExecutor threadpool = new ThreadPoolExecutor(15, 15,
            10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    private static final ConcurrentLinkedQueue<DeformationCheck> dataList = new ConcurrentLinkedQueue<>();

    @Bean
    public void createConnection() {
        if (enable) {
            try {
                Socket clientSocket = new Socket(ip, port);
                threadpool.execute(new ClientHandler(clientSocket, startFlag, endFlag));
                threadpool.execute(new DataSaver());
            } catch (IOException e) {
                log.error("Failed to create socket connection", e);
            }
        } else {
            log.info("Deformation check socket is disabled.");
        }
    }

    private static class ClientHandler implements Runnable {
        private final Socket clientSocket;
        private final String startFlag;
        private final String endFlag;

        public ClientHandler(Socket socket, String startFlag, String endFlag) {
            this.clientSocket = socket;
            this.startFlag = startFlag;
            this.endFlag = endFlag;
        }

        @Override
        public void run() {
            try (OutputStream ops = clientSocket.getOutputStream();
                 OutputStreamWriter opsw = new OutputStreamWriter(ops);
                 BufferedWriter bw = new BufferedWriter(opsw);
                 InputStream ips = clientSocket.getInputStream();
                 InputStreamReader ipsr = new InputStreamReader(ips);
                 BufferedReader br = new BufferedReader(ipsr)) {

                // 向服务端程序发送数据
                bw.write(startFlag + "\n");
                bw.flush();

                // 从服务端程序接收数据
                String s;
                while ((s = br.readLine()) != null) {
                    String[] result = s.split(",");
                    if (result != null && result.length == 5) {
                        try {
                            DeformationCheck deformationCheck = new DeformationCheck();
                            deformationCheck.setJth(result[0]);
                            deformationCheck.setCpgg(result[1]);
                            deformationCheck.setQxsl(Integer.parseInt(result[2]));
                            deformationCheck.setXlzj(Double.parseDouble(result[3]));
                            deformationCheck.setAlermFlag("True".equals(result[4]) ? "1" : "0");
                            deformationCheck.setCreateTime(new Date());
                            dataList.add(deformationCheck);
                            log.info(deformationCheck.toString());
                        } catch (Exception e) {
                            log.error("Error processing deformation data", e);
                        }
                    }
                }

            } catch (IOException e) {
                log.error("Error in client handler", e);
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    log.error("Failed to close client socket", e);
                }
            }
        }
    }

    private static class DataSaver implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    if (dataList.size() > 10) {
                        IDeformationCheckService deformationCheckService = SpringBeanUtils.getApplicationContext().getBean(IDeformationCheckService.class);
                        deformationCheckService.saveBatch(new ArrayList<>(dataList));
                        dataList.clear();
                    }
                } catch (Exception e) {
                    log.error("Error saving deformation data", e);
                }
                try {
                    Thread.sleep(5000); // 每5秒尝试一次
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("DataSaver thread interrupted", e);
                }
            }
        }
    }
}
